package com.lwj.utils;

import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifDirectoryBase;
import com.lwj.exception.BusinessException;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;

public class ImageUtils {

    protected static final Logger logger = LoggerFactory.getLogger(ImageUtils.class);

    /**
     * 压缩图片
     * @param file
     * @param size 图片大小
     * @return
     * @throws Exception
     */
    public static byte[] imageChangeSize(File file, Integer size) throws Exception {
        File newFile = null;
        ByteArrayOutputStream out = null;
        ByteArrayOutputStream out2 = null;
        try {
            /*图片的原始宽 120*/
            int oldWidth;
            /*图片的原始高 120*/
            int oldHeight;
            /*图片修改后的宽 0*/
            int newWidth = 0;
            /*图片修改后的高 0*/
            int newHeight = 0;
            BufferedImage bufImg = ImageIO.read(file);
            /*图片的原始宽度*/
            oldWidth = bufImg.getWidth();
            /*图片的原始高度*/
            oldHeight = bufImg.getHeight();
            //
            float rate = (float) oldWidth / (float) oldHeight;
            int angle = getiphonePicAngle(file);
            if (size != null && (size == 250 || size == 2000 || size == 500)) {
                if (oldHeight >= oldWidth) {
                    if (oldHeight > size) {
                        newHeight = size;
                        newWidth = (int) (newHeight * rate);
                    } else {
                        newHeight = oldHeight;
                        newWidth = oldWidth;
                    }
                } else {
                    if (oldWidth > size) {
                        newWidth = size;
                        newHeight = (int) (newWidth / rate);
                    } else {
                        newHeight = oldHeight;
                        newWidth = oldWidth;
                    }
                }
            } else {
                newHeight = oldHeight;
                newWidth = oldWidth;
            }
            /*开始改变大小*/
            BufferedImage bf = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);

            bf.getGraphics().fillRect(0, 0, newWidth, newHeight);
            bf.getGraphics().drawImage(bufImg, 0, 0, newWidth, newHeight, null);
            out = new ByteArrayOutputStream();
            //转换编码格式JPEG
            ImageIO.write(bf, "JPEG", out);
            byte[] re = out.toByteArray();

            if (angle != 0) {

                String fileName = System.currentTimeMillis() + file.getName();
                newFile = new File(fileName);
                FileUtils.writeByteArrayToFile(newFile, re);
                BufferedImage bufferedImage = getRotateImage( angle,newFile);
                out2 = new ByteArrayOutputStream();
                ImageIO.write(bufferedImage, "JPEG", out2);
                return out2.toByteArray();
            }
            return re;
        } catch (Exception e) {
            logger.error("转换图片错误", e);
            throw new BusinessException("转换图片错误");
        } finally {
            if (newFile != null) {
                newFile.delete();
            }
             close(out2,out);
        }
    }

    public static void close(Closeable... closeables){
        for (int i = 0; i < closeables.length; i++) {
            Closeable closeable = closeables[i];
            try {
                if(closeable!=null){
                    closeable.close();
                }
            }catch (Exception e){

            }
        }
    }

    /**
     * 旋转图片
     * @param angel 角度
     * @param file  文件
     * @return
     * @throws IOException
     */
    public static BufferedImage getRotateImage(int angel, File file) throws IOException {
        Image img = ImageIO.read(file);
        int srcWidth = img.getWidth(null);
        int srcHeight = img.getHeight(null);
        Rectangle rectDes = calcRotatedSize(new Rectangle(new Dimension(srcWidth, srcHeight)), angel);
        BufferedImage bufferedImage = new BufferedImage(rectDes.width, rectDes.height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = bufferedImage.createGraphics();
        // 平移
        g2.translate((double) (rectDes.width - srcWidth) / 2, (double) (rectDes.height - srcHeight) / 2);
        // 旋转变换
        g2.rotate(Math.toRadians(angel), (double) srcWidth / 2, (double) srcHeight / 2);
        g2.drawImage(img, null, null);
        g2.dispose();
        return bufferedImage;
    }

    public static int getiphonePicAngle(File file) throws Exception {
        Metadata metadata = ImageMetadataReader.readMetadata(file);
        Directory directory = metadata.getFirstDirectoryOfType(ExifDirectoryBase.class);
        int orientation = 0;
        // Exif信息中有保存方向,把信息复制到缩略图
        // 原图片的方向信息
        if (directory != null && directory.containsTag(ExifDirectoryBase.TAG_ORIENTATION)) {
            orientation = directory.getInt(ExifDirectoryBase.TAG_ORIENTATION);
        }
        int angle = 0;
        if (6 == orientation) {
            //6旋转90
            angle = 90;
        } else if (3 == orientation) {
            //3旋转180
            angle = 180;
        } else if (8 == orientation) {
            //8旋转90
            angle = 270;
        }
        return angle;
    }

    /**
     * 计算旋转后的图片大小
     * @param src
     * @param angel
     * @return
     */
    private static Rectangle calcRotatedSize(Rectangle src, int angel) {
        // 如果旋转的角度大于90度，需要进行转换
        if (angel >= 90) {
            if (angel / 90 % 2 == 1) {
                int temp = src.height;
                src.height = src.width;
                src.width = temp;
            }
            angel = angel % 90;
        }
        double r = Math.sqrt((double) (src.height * src.height + src.width * src.width)) / 2;
        double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
        double angelAlpha = (Math.PI - Math.toRadians(angel)) / 2;
        double angelDaltaWidth = Math.atan((double) src.height / src.width);
        double angelDaltaHeight = Math.atan((double) src.width / src.height);

        int lenDaltaWidth = (int) (len * Math.cos(Math.PI - angelAlpha - angelDaltaWidth));
        int lenDaltaHeight = (int) (len * Math.cos(Math.PI - angelAlpha - angelDaltaHeight));
        int desWidth = src.width + lenDaltaWidth * 2;
        int desHeight = src.height + lenDaltaHeight * 2;
        return new Rectangle(new Dimension(desWidth, desHeight));
    }
}
